package org.ace.logic.map.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.ace.logic.map.model.MoveDTO;
import org.ace.logic.map.protocol.MapProtocol;
import org.ace.logic.user.dto.PlayerDTO;

import javax.annotation.Resource;

import io.netty.channel.Channel;

import org.ace.dao.model.Player;
import org.ace.endingCode.SocketModel;
import org.ace.logic.AbstractHandlerServImpl;
import org.ace.logic.IHandlerServ;
import org.ace.model.Vector3;
import org.ace.protocol.Protocol;
import org.ace.tool.IExecutorPool;
import org.ace.tool.ISchedule;

import static org.ace.logic.map.protocol.MapProtocol.*;
/*对数据库操作封装在abstractHandlerServImpl ,直接是在这个二级区域里面进行 三级判断*/
public class MapHandlerServImpl extends AbstractHandlerServImpl implements
		IHandlerServ {

	/*单线程池管理器*/
	@Resource(name="executorPool")
	private IExecutorPool executorPool;

	@Resource(name="schedule")
	private ISchedule schedule;
	
	/*延迟队列 ，优化,服务器对客户端数据 的同步 不用每时每刻同步，没200-500ms同步一次*/
	private Map<Integer ,MoveDTO> moveList = new ConcurrentHashMap<Integer, MoveDTO>();
	
	/*设置模块*/
	@Override
	public int getType()
	{
	    return Protocol.TYPE_MAP;
	}
	
	private void init()
	{
		moveSync();
	}
	
	private void moveSync()
	{
		schedule.schedule(new Runnable(){
			@Override
			public void run(){
				 if(moveList.size()>0)
				 {/*发送完所有消息 ，清空列表*/
					 brocast(MOVE_BRO,moveList.values().toArray());
					 moveList.clear();
				 }
				 //递归调用
				 moveSync();
			}// 移动延迟队列 ，200 -500 ms之间同步一次最佳
		}, 200);
		   
	}
	
	@Override
	protected void process(Channel channel, SocketModel message) {
		switch(message.getCommand())
		{
		case ENTER_CREQ:
			enter(channel,message);
			break;
		case LEAVE_CREQ:
			leave(channel);
			break;
		case MOVE_CREQ:
			move(channel,message);
			break;
		case TALK_CREQ:
			talk(channel,message);
			break;
		}

	}

	private void talk(Channel channel, SocketModel message) {
		brocast(TALK_BRO, message.getMessage());
		
	}

	/**移动更新*/
	private void move(Channel channel, SocketModel<MoveDTO> message) {
		final Integer userId = getUserId(channel);
		final MoveDTO move = message.getMessage();
		/*修改当前位置*/
		executorPool.execute(new Runnable(){
			@Override
			public void run(){
				playerBiz.changeMap(userId, getArea(), move.position.x, move.position.y, move.position.z);
			}
		});
		/*不直接发送 ，不需要实时更新 做延迟队列 */
		move.userId = userId;
		
		moveList.put(userId, move);
	}

	/**移除*/
	public boolean leave(Channel channel) {
		//
		Integer userId = getUserId(channel);
		/*是否移除成功*/
		if(super.leave(channel))
		{
			/*群发移除的 角色 */
			brocast(LEAVE_BRO,userId);
		}
		return true;
	}

	/**角色进入地图处理函数 */
	private void enter(Channel channel, SocketModel<Vector3> message) {
		final  Vector3 v = message.getMessage();
		final Integer userId=getUserId(channel);
		/*已存在返回*/
		if(enterd(userId))
		{
			return;
		}
		/*添加添加Map 里角色 id 和 channel的绑定*/
		enter(channel);
		executorPool.execute(new Runnable(){
			@Override
			public void run()
			{/*修改存储数据*/
				playerBiz.changeMap(userId, getArea(), v.x, v.y, v.z);
			}
		});
		/*没有用数据安全隐患逻辑 放在逻辑层 多线程处理*/
		PlayerDTO dto = new PlayerDTO(playerBiz.get(userId));
		dto.x = v.x;
		dto.y = v.y;
		dto.z = v.z;
		/*区域群发*/
		brocast(channel,ENTER_BRO,dto);
		write(channel,ENTER_SRES,getDTOs(getRoles()));
		
	}

	/**获取区域 角色成员*/
	private PlayerDTO[] getDTOs(Player[] player)
	{
		PlayerDTO[] dtos =new PlayerDTO[player.length];
		/*获取到自身坐标数据不一致实时 进行移动功能开发 修正,*/
		for(int i=0;i<dtos.length;i++)
		{
			dtos[i]=new PlayerDTO(player[i]);																												
		}
		return dtos;
	}
	@Override
	protected void channelClose(Channel channel) {
		leave(channel);
	}

}
